/**
 *       Copyright (c) 2012 Lukas Zaruba
 *
 *   This file is part of Robot Playground.
 *
 *   Robot Playground is free software: you can redistribute it and/or modify
 *   it under the terms of the GNU Lesser General Public License as published by
 *   the Free Software Foundation, either version 3 of the License, or
 *   (at your option) any later version.
 *
 *   Robot Playground is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU Lesser General Public License for more details.
 *
 *   You should have received a copy of the GNU Lesser General Public License
 *   along with Robot Playground. If not, see <http://www.gnu.org/licenses/>.
 */
package net.zarubsys.robotplayground.core;

import java.util.ArrayList;
import java.util.List;

import net.zarubsys.robotplayground.core.device.IDevice;
import net.zarubsys.robotplayground.core.modules.IModule;
import net.zarubsys.robotplayground.core.modules.IModuleConfiguration;
import net.zarubsys.robotplayground.core.modules.INotificationCause;
import net.zarubsys.robotplayground.core.program.API;
import net.zarubsys.robotplayground.core.program.IStopListener;

import org.apache.log4j.Logger;
import org.eclipse.core.runtime.Assert;

/**
 * Environment
 * 
 * Environment is used in the runtime to tie together different modules,
 * devices, programs and monitors. They all share one instance of this class
 * in one run.
 * 
 * Developers are supposed to use only documented methods
 *
 * @author Lukas Zaruba, lukas.zaruba@gmail.com
 */
public class Environment {
	
	private static final Logger ENV_LOG = Logger.getLogger("sessionLog");
	private static final Logger LOG = Logger.getLogger(Environment.class); // not yet used
	
	public static final String LOG_PATH_KEX = "logPath";
	
	private API api;
	private List<IStopListener> stopListeners = new ArrayList<>();
	private final String logPath;
	
	public Environment(String logPath) {
		this.logPath = logPath;
	}
	
	/**
	 * @return valid instance of {@link Logger} for this running session.
	 */
	public Logger getLogger() {
		return ENV_LOG;
	}
	
	public void setAPI(API api) {
		this.api = api;
	}
	
	public API getAPI() {
		return api;
	}
	
	/**
	 * Provides access to the path of the current running session
	 * log file.
	 */
	public String getLogPath() {
		return logPath;
	}
	
	/**
	 * Use this method if you want to register to be notified once
	 * the running session ended.
	 */
	public void registerStopListener(IStopListener listener) {
		stopListeners.add(listener);
	}

	/**
	 * Use this method to dispatch notification to anybody who listens to it.
	 * @param module instance of the module dispatching the notification
	 * @param cause cause of the notification. Modules are expected to create 
	 * own implementations of this interface.
	 */
	public void dispatchNotification(IModule<? extends IDevice, ? extends IModuleConfiguration> module, INotificationCause cause) {
		Assert.isNotNull(api, "API must be set before using environment!");
		api.dispatchNotification(module, cause);
	}
	
	/**
	 * Call this method if the running session should be stopped for some reason.
	 * These might include illegal state of the session, internal error of the 
	 * session object or anything else.
	 * @param caller instance of the object which called the stop
	 * @param message message which will be passed around and logged. It should be
	 * as descriptive as possible.
	 */
	public void stop(Object caller, String message) {
		Assert.isNotNull(caller, "Caller must not be null!");
		ENV_LOG.info("Stop was called! Caller: '" + caller.getClass().getName() + "' - " + caller.toString() + ", message: " + message, new RuntimeException("No exception, just stacktrace"));
		for (IStopListener stopListener : stopListeners) {
			stopListener.stop(caller, message);
		}
		api.stop();
	}
	
}

